package com.zy.je.common.core.model;

import com.zy.je.common.core.utils.lang.MapTypeConverter;
import com.zy.je.common.core.utils.lang.StackUtil;
import com.zy.je.common.core.utils.lang.StringUtil;
import lombok.extern.slf4j.Slf4j;

import java.util.LinkedHashMap;
import java.util.regex.Pattern;

/**
 * 兼容FastJSON和Jackson的动态POJO基类
 * 特点：
 * 1. 固定属性和动态属性在JSON中平级展示
 * 2. 两种序列化库都能正确序列化/反序列化
 * 3. 不需要特殊序列化配置
 * 注意事项：
 * 1、此类只是对map的增强，不适用于自己定义单独的字段 以及使用lombok工具
 *
 * @author zy
 */
@Slf4j
public class DynamicObj extends LinkedHashMap<String, Object> {
    public <T> void set(String key, T value, Class<T> type) {
        this.put(key, value);
    }

    public <T> T get(String key, Class<T> type) {
        return MapTypeConverter.getValue(this, key, type);
    }

    protected <T> void set(T value, Class<T> type) {
        String key = getCurPropertyName();
        log.debug("set:{}", key);
        set(key, value, type);
    }

    protected <T> T get(Class<T> type) {
        String key = getCurPropertyName();
        log.debug("get:{}", key);
        return get(key, type);
    }

    /**
     * 是否使用驼峰模式
     *
     * @return
     */
    protected boolean useSnackMode() {
        return true;
    }

    // 防止FastJSON将此类识别为Map而特殊处理
    public Class<?> getClassType() {
        return this.getClass();
    }


//    // 示例固定属性（实际使用时可以覆盖这些方法）
//    public String getName() {
//        return get("name",String.class);
//    }
//
//    public void setName(String name) {
//        set("name", name,String.class);
//    }

    private static final Pattern GET_PATTERN = Pattern.compile("^get[A-Z].*");
    private static final Pattern SET_PATTERN = Pattern.compile("^set[A-Z].*");
    private static final Pattern IS_PATTERN = Pattern.compile("^is[A-Z].*");

    protected String getCurPropertyName() {
        String methodName = StackUtil.getCallerMethodName(3);
        if (GET_PATTERN.matcher(methodName).matches()) {
            methodName = methodName.substring(3);
        } else if (SET_PATTERN.matcher(methodName).matches()) {
            methodName = methodName.substring(3);
        } else if (IS_PATTERN.matcher(methodName).matches()) {
            methodName = methodName.substring(2);
        }
        if (useSnackMode()) {
            return StringUtil.uncapitalize(methodName);
        } else {
            return StringUtil.uncamelCase(methodName);
        }
    }

//    private static final StackWalker STACK_WALKER = StackWalker.getInstance();
//
//    protected static String getCallerMethodName(int skip) {
//        return STACK_WALKER.walk(stackFrames -> stackFrames
//                .skip(skip) // 跳过getCurrentMethodName方法本身
//                .findFirst()
//                .map(StackWalker.StackFrame::getMethodName)
//                .orElse(""));
//    }
}
